package cn.miaoyao.miaoyaoms.service.impl;
import cn.miaoyao.miaoyaoms.entity.Miaosample;
import cn.miaoyao.miaoyaoms.entity.Notice;
import cn.miaoyao.miaoyaoms.entity.User;
import cn.miaoyao.miaoyaoms.service.MiaosampleService;
import cn.miaoyao.miaoyaoms.service.NoticeService;
import cn.miaoyao.miaoyaoms.service.UserService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import org.mybatis.logging.Logger;
import org.mybatis.logging.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
/**
 * @Author: shushu
 * @Date: 2023/05/08/13:52
 * @Description:websocket服务类，主要是将目前的类定义成一个websocket服务器端，注解的是值将被用于监听用户连接的终端
 * 访问url地址，客户端可以通过这个url地址来连接到websocket服务器端
 */
@ServerEndpoint(value = "/websocket")
@Component
@EnableScheduling// cron定时任务
@Data
public class WebSocketServiceImpl {
    private static final Logger logger= LoggerFactory.getLogger(WebSocketServiceImpl.class);
    /**
     * 静态变量，用来记录当前的用户登录人数，应设置为线程安全的。
     */
    private static int onlineCount=0;
    /**
     * concurrent包下线程安全的set集合类。用来存放每个客户端对应的mySocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketServiceImpl> webSocketSet=new CopyOnWriteArraySet<>();
    /**
     * 与某个客户端的连接会话，需要通过session来给客户端发送数据
     */
    private Session session;
   private static LambdaQueryWrapper<Notice> nsw = new LambdaQueryWrapper<Notice>();

    public static CopyOnWriteArraySet<WebSocketServiceImpl> getWebSocketSet(){
        return webSocketSet;
    }

    public static void setWebSocketSet(CopyOnWriteArraySet<WebSocketServiceImpl> webSocketSet){
        WebSocketServiceImpl.webSocketSet=webSocketSet;
    }

    /**
     * 从数据库查询相关数据信息。
     */
    @Autowired
    private UserService userService;
    private static UserService userS;
    @Autowired
    private MiaosampleService miaosampleService;
    private static MiaosampleService miaoS;
    @Autowired
    private NoticeService noticeService;
    private static NoticeService notice;


    @PostConstruct //当这个启动类启动的时候，执行下面这个方法。
    public void init(){
        WebSocketServiceImpl.userS=this.userService;
        WebSocketServiceImpl.miaoS=this.miaosampleService;
        WebSocketServiceImpl.notice=this.noticeService;

    }
    /**
     * 连接建立成功之后的回调函数（连接执行之后就执行该方法）
     * @param session
     * @throws Exception
     */
    @OnOpen
    public void onOpen(Session session)throws Exception{
        System.out.println("连接已建立");
        this.session=session;
        webSocketSet.add(this);//将建立连接之后的用户Jsessionid存入到这个set集合中。
        int userCount=userS.count(new LambdaQueryWrapper<User>().eq(User::getDeleted,"0"));//用户数量
        int miaosampleCount=miaoS.count(new LambdaQueryWrapper<Miaosample>().eq(Miaosample::getStatus,1));//药材数量
        //LambdaQueryWrapper<Notice> nsw = new LambdaQueryWrapper<Notice>();
        nsw.orderByDesc(Notice::getNoticetime).last("limit 5");
        List<Notice> list = notice.list(nsw);
        nsw.clear();
        HashMap<String, Object> map = new HashMap<>();
        map.put("userCount",userCount);
        map.put("miaosampleCount",miaosampleCount);
        map.put("notice",JSON.toJSONString(list));
        System.out.println();
        String message = JSON.toJSONString(map);
        this.sendMessage(message);
    }

    /**
     * 发送信息
     * @param message 进行消息发送的具体数据。
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException{
        System.out.println(message);
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 自定义消息发送，可群发，也可单发
     * @param message
     * @throws IOException
     */
    public static void sendInfo(String message) throws IOException{
        for(WebSocketServiceImpl item:webSocketSet){
            item.sendMessage(message);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);
        if(session!=null){
            try{
                System.out.println("连接已关闭");
                session.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 发生错误时调用该方法
     * @param session 会话
     * @param throwable 错误信息
     */
    @OnError
    public void onError(Session session,Throwable throwable){
        System.out.println("连接异常");
        throwable.printStackTrace();
    }
}
